import { h, render } from 'vue';

const IconLoading = {
  name: 'IconLoading',
  displayName: 'IconLoading',
  props: {
    color: String,
  },
  setup(props) {
    let color = props.color || '#1890ff';
    return () => {
      return h(
        'svg',
        {
          xmlns: 'http://www.w3.org/2000/svg',
          version: '1.1',
          width: '80',
          height: '80',
          viewBox: '0 0 80 80',
          baseProfile: 'full',
        },
        [
          h('g', { fill: color }, [
            h('circle', { cx: '25', cy: '25', r: '12', 'fill-opacity': '1' }),
            h('circle', { cx: '55', cy: '25', r: '12', 'fill-opacity': '0.7' }),
            h('circle', { cx: '55', cy: '55', r: '12', 'fill-opacity': '0.5' }),
            h('circle', { cx: '25', cy: '55', r: '12', 'fill-opacity': '0.2' }),
            h('animateTransform', {
              attributeName: 'transform',
              begin: '0s',
              dur: '1s',
              type: 'rotate',
              from: '0 40 40',
              to: '360 40 40',
              repeatCount: 'indefinite',
            }),
          ]),
        ]
      );
    };
  },
};

const CLoading = {
  name: 'CLoading',
  displayName: 'CLoading',
  props: { ...IconLoading.props, size: String },
  setup(props) {
    const sizeEnum = { small: '30px', medium: '50px', large: '80px' };
    const size = sizeEnum[props.size] || sizeEnum.small;
    const style = {
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      position: 'absolute',
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
      zIndex: 999999,
      background: 'rgba(255,255,255,0.1)',
    };
    return () => {
      return h('div', { style }, h(IconLoading, { ...props, style: { width: size, height: size } }));
    };
  },
};

const createLoadingVNode = (container, props) => {
  function show() {
    clearTimeout(this._timer);
    this._timer = setTimeout(() => {
      if (this._container && this._container.nodeType === 1) {
        let position = this._container.style.position;
        this._container.setAttribute('position', position);
        this._container.style.position = 'relative';
        render(this, this._container);
      }
    }, 100);
  }
  function hide() {
    clearTimeout(this._timer);
    render(null, this._container);
    let position = this._container.getAttribute('position');
    this._container.removeAttribute('position');
    this._container.style.position = position || null;
    this.el = null;
  }
  const vNode = h(CLoading, props);
  if (container && container.nodeType === 1) {
    vNode._container = container;
  }
  vNode.show = show;
  vNode.hide = hide;
  return vNode;
};

const loading = (() => {
  let container = document.getElementById('app') || document.body;
  let vNode = createLoadingVNode(container, { size: 'medium' });
  // debugger;
  return {
    show: () => vNode.show(),
    hide: () => vNode.hide(),
  };
})();

const install = (app) => {
  app.component(CLoading.name, CLoading);
  app.directive('loading', {
    created(el, binding, vnode) {
      const { size, color } = Object.assign({}, binding.value);
      const vNode = createLoadingVNode(el, { size, color });
      vNode.appContext = vnode.ctx.appContext;
      el._loading = vNode;
      el._toggle = (el, binding) => {
        if (typeof binding.value === 'boolean') {
          binding.value ? el._loading.show() : el._loading.hide();
        } else {
          const { show } = Object.assign({}, binding.value);
          show === true ? el._loading.show() : el._loading.hide();
        }
      };
      el._toggle(el, binding);
    },
    updated(el, binding) {
      el._toggle(el, binding);
    },
    unmounted(el) {
      el._loading = null;
      el._toggle = null;
    },
  });
};

export { install as default, loading, CLoading, IconLoading };
